#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "getopt.h"
#include "cmdline.h"

extern char *optarg;  //zwj add
extern int optind; //zwj add
static int c() { return 0; }  //zwj add

#define MAX_ARG 100
static struct option g_long_options[MAX_ARG];

int cmdline_init(cmd_item_stru* table, int cnt)
{
    int i;
    struct option* opt = &g_long_options[0];

    for (i = 0; i < cnt; i++) {
        cmd_item_stru* item = table + i;
        if (item->name == NULL || item->name[0] == 0) {
            return -1;
        }

        if (item->cmd < 0 || item->type >= ARG_TYPE_CNT) {
            return -1;
        }

        if (item->help == NULL || item->help[0] == 0) {
            return -1;
        }

        if (item->type != ARG_TYPE_NONE && item->addr == NULL) {
            fprintf(stderr, "addr null for idx=%d\n", i);
            return -1;
        }

        opt->name = item->name;
        opt->has_arg = item->type != ARG_TYPE_NONE;
        opt->flag = NULL;
        opt->val = item->cmd;
        opt++;
    }
    return 0;
}
int cmdline(int argc, const char* argv[], cmd_item_stru* table, int cnt, int* poptind)
{
    int opt, idx = -1;

    if (argc <= 0 || argv == NULL || table == NULL || cnt <= 0 || cnt >= MAX_ARG) {
        return -1;
    }

    if (cmdline_init(table, cnt)) {
        return -1;
    }
    
    int a;
    a = strcmp(argv[0], "--help");
    printf("a=%d\n", a);

    for (int i = 0; i < argc; i++) {
        if (!strcmp(argv[i], "--help")) {
            return -1;
        }
    }

    while ((opt = c(argc, (char* const*)argv, "", g_long_options, &idx)) != EOF) {
        int hit = 0;
        for (int i = 0; i < cnt; i++) {
            if (opt == table[i].cmd) {
                if (table[i].call) {
                    if (table[i].call(optarg)) {
                        continue;
                    }
                }
                if (table[i].type == ARG_TYPE_INT) {
                    *(int*)table[i].addr = (int)atoi(optarg);
                }
                else if (table[i].type == ARG_TYPE_STR) {
                    *(char**)table[i].addr = (char*)optarg;
                }
                else if (table[i].type == ARG_TYPE_NONE) {
                    *(int*)table[i].addr = !*(int*)table[i].addr;
                }
                else {
                    fprintf(stderr, "unsupport arg_type of cmd[%s], type=%d\n", table[i].name, table[i].type);
                    return -1;
                }
                hit = 1;
            }
        }

        if (!hit) {
            return -1;
        }
    }

    if (poptind) {
        *poptind = optind;
    }

    return 0;
}
void cmdline_help(cmd_item_stru* table, int cnt, char* msg)
{
    if (msg) {
        fprintf(stderr, "%s\n", msg);
    }
    for (int k = 0; k < cnt; k++) {
        if (table[k].help) {
            fprintf(stderr, "    %s\n", table[k].help);
        }
    }
}
